package cn.org.rapid_framework.web.session.store;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.sql.DataSource;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
// #TODO fixed me, cannot use sun.misc.BASE64Decoder
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
*
* 用于将session存储在数据库中
*
* 数据库表结构如下:
* <pre>
* CREATE TABLE http_session_store (
* session_id char(40) PRIMARY KEY,
* session_data text,
* expire_date bigint
* );
* </pre>
*
* @author badqiu
*
*/
@SuppressWarnings("all")
public class JdbcSessionStore extends SessionStore{
DataSource dataSource;
static String DELETE = "delete from http_session_store where session_id = ?";
static String INSERT = "insert into http_session_store(session_id,expire_date,session_data) values (?,?,?)";
static String GET = "select session_data from http_session_store where session_id = ? and expire_date >= ?";
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void deleteSession(String sessionId) {
getSimpleJdbcTemplate().update(DELETE, sessionId);
}
public Map getSession(String sessionId,int timeoutSeconds) {
List<Map> results = getSimpleJdbcTemplate().query(GET,new ParameterizedRowMapper<Map>(){
public Map mapRow(ResultSet rs, int row) throws SQLException {
String sessionData = rs.getString(1);
return decode(sessionData);
}
},sessionId,System.currentTimeMillis());
return results.size() > 0 ? results.get(0) : new HashMap();
}
public void saveSession(String sessionId,Map sessionData,int timeoutSeconds) {
deleteSession(sessionId);
String data = encode(sessionData);
Timestamp expire_date = computeExpireDate(timeoutSeconds);
getSimpleJdbcTemplate().update(INSERT, sessionId,expire_date.getTime(),data);
}
private Timestamp computeExpireDate(int timeoutSeconds) {
// Timestamp now = new Timestamp(System.currentTimeMillis());
// CalendarUtils.add(Calendar.SECOND, now, timeoutSeconds);
// return now;
return new Timestamp(System.currentTimeMillis()+ (timeoutSeconds * 1000));
}
private SimpleJdbcTemplate getSimpleJdbcTemplate() {
return new SimpleJdbcTemplate(dataSource);
}
static Pattern sessionDataParser = Pattern.compile("\u0000([^:]*):([^\u0000]*)\u0000");
public static Map decode(String sessionData) {
ObjectInputStream ois;
try {
ois = new ObjectInputStream(new ByteArrayInputStream(new BASE64Decoder().decodeBuffer(sessionData)));
return (Map)ois.readObject();
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("decode session data error:UnsupportedEncodingException",e);
} catch (IOException e) {
throw new RuntimeException("decode session data error:IOException",e);
} catch (ClassNotFoundException e) {
throw new RuntimeException("decode session data error:ClassNotFoundException",e);
}
}
public static String encode(Map<String,?> sessionData) {
try {
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(byteOutput);
oos.writeObject(sessionData);
byte[] bytes = byteOutput.toByteArray();
return new BASE64Encoder().encode(bytes);
}catch(IOException e) {
throw new RuntimeException("encode session data error",e);
}
}
}